#include <stdio.h>
#include <gmp.h>
#include <pthread.h>

pthread_t threads[2];

    //variaveis globais
    mpf_t a_n;         //An
    mpf_t a_n1;        //An+1
    mpf_t b_n;         //Bn
    mpf_t b_n1;        //Bn+1
    mpf_t t_n;         //Tn
    mpf_t t_n1;        //Tn+1
    mpf_t p_n;         //Pn
    mpf_t p_n1;        //Pn+1
    int k;

void *calcula_p(void *arg){

    //calculo de Pn+1
    mpf_mul_ui(p_n1, p_n, 2);

    //espera outra thread terminar o calculo
    pthread_join(threads[1], NULL);

    //atualiza variavel
    mpf_set(p_n, p_n1);

    pthread_exit(NULL);
}

void *calcula_abt(void *arg){

    mpf_t aux, aux2, aux3, aux4, aux5;

    mpf_init(aux);
    mpf_init(aux2);
    mpf_init(aux3);
    mpf_init(aux4);
    mpf_init(aux5);

    //calculo de An+1
    mpf_add(aux, a_n, b_n);
    mpf_div_ui(a_n1, aux, 2);

    //calculo de Bn+1
    mpf_mul(aux2, a_n, b_n);
    mpf_sqrt(b_n1, aux2);

    //calculo de Tn+1
    mpf_sub(aux3, a_n, a_n1);
    mpf_pow_ui(aux4, aux3, 2);
    mpf_mul(aux5, p_n, aux4);
    mpf_sub(t_n1, t_n, aux5);

    mpf_clear(aux);
    mpf_clear(aux2);
    mpf_clear(aux3);
    mpf_clear(aux4);
    mpf_clear(aux5);

    //atualiza variaveis
    mpf_set(a_n, a_n1);
    mpf_set(b_n, b_n1);
    mpf_set(t_n, t_n1);

    pthread_exit(NULL);
}

int main(){

    mpf_set_default_prec(35000000);

    mpf_t pi;
    mpf_t aux, aux2, aux3;

    mpf_init(a_n);
    mpf_init(a_n1);
    mpf_init(b_n);
    mpf_init(b_n1);
    mpf_init(t_n);
    mpf_init(t_n1);
    mpf_init(p_n);
    mpf_init(p_n1);
    mpf_init(pi);
    mpf_init(aux);
    mpf_init(aux2);
    mpf_init(aux3);

    //valor inicial das variaveis
    mpf_set_ui(a_n, 1);
    mpf_sqrt_ui(b_n,2);
    mpf_ui_div(b_n, 1, b_n);
    mpf_set_ui(t_n, 1);
    mpf_div_ui(t_n,t_n,4);
    mpf_set_ui(p_n, 1);

    for(k = 0; k <= 22; k++){
        pthread_create(&threads[0], NULL, calcula_p, NULL);
        pthread_create(&threads[1], NULL, calcula_abt, NULL);

        pthread_join(threads[0], NULL);

		//calculo do pi
        mpf_add(aux, a_n, b_n);
        mpf_pow_ui(aux2, aux, 2);
        mpf_mul_ui(aux3, t_n, 4);
        mpf_div(pi, aux2, aux3);

        //imprime valor do pi
        //printf("k: %d\n", k);
        //gmp_printf("Pi %.1000000Ff\n", pi);
    }

    mpf_clear(a_n);
    mpf_clear(a_n1);
    mpf_clear(b_n);
    mpf_clear(b_n1);
    mpf_clear(t_n);
    mpf_clear(t_n1);
    mpf_clear(p_n);
    mpf_clear(p_n1);
    mpf_clear(pi);
    mpf_clear(aux);
    mpf_clear(aux2);
    mpf_clear(aux3);

    return(0);
}
